package com.zbl.zblproject.erp.service.impl;

import com.alipay.demo.trade.utils.GoodDateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.base.Preconditions;
import com.zbl.zblproject.contract.mapper.ContractMapper;
import com.zbl.zblproject.core.entity.AdminUser;
import com.zbl.zblproject.core.entity.Supplier;
import com.zbl.zblproject.core.mapper.AdminUserMapper;
import com.zbl.zblproject.core.mapper.BrandMapper;
import com.zbl.zblproject.core.mapper.SupplierMapper;
import com.zbl.zblproject.erp.controller.ErpFinanceLogController;
import com.zbl.zblproject.erp.entity.*;
import com.zbl.zblproject.erp.mapper.*;
import com.zbl.zblproject.erp.service.ErpInventoryService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;

/**
 * @author youlanqiang
 * @version 1.0
 * @date 2018/10/19
 */
@Service
public class ErpInventoryServiceImpl implements ErpInventoryService {


    @Autowired
    private ErpInventoryOrderMapper inventoryOrderMapper;

    @Autowired
    private ErpInventoryOrderItemMapper inventoryOrderItemMapper;

    @Autowired
    private ErpGoodMapper erpGoodMapper;

    @Autowired
    private ErpWarehouseItemMapper warehouseItemMapper;

    @Autowired
    private ErpLeaveItemMapper leaveItemMapper;


    @Autowired
    private BrandMapper erpBrandMapper;

    @Autowired
    private BalanceMapper balanceMapper;

    @Autowired
    private ErpCategoryMapper erpCategoryMapper;

    @Autowired
    private SupplierMapper erpSupplierMapper;

    @Autowired
    private ErpWarehouseMapper erpWarehouseMapper;

    @Autowired
    private AdminUserMapper adminUserMapper;

    @Autowired
    private ErpFinanceLogMapper erpFinanceLogMapper;

    @Autowired
    private SupplierMapper supplierMapper;

    @Autowired
    private ContractMapper contractMapper;

    @Autowired
    private ErpWarehouseItemMapper erpWarehouseItemMapper;

    private static final Logger logger = LoggerFactory.getLogger(ErpInventoryService.class);


    @Override
    public ErpInventoryOrder getOrderBySn(String orderSn) {
        QueryWrapper<ErpInventoryOrder> wrapper = new QueryWrapper<>();
        wrapper.eq("inventory_sn", orderSn);
        ErpInventoryOrder order = inventoryOrderMapper.selectOne(wrapper);
        return order;
    }

    @Override
    public boolean updateOrderContext(String orderSn, String context) {
        ErpInventoryOrder order = getOrderBySn(orderSn);
        if (order == null) {
            return false;
        }
        order.setContext(context);
        return inventoryOrderMapper.updateById(order) == 1;
    }

    @Override
    public boolean rollback(int id) {
        ErpInventoryOrder order = inventoryOrderMapper.selectById(id);
        if (order == null) {
            throw new RuntimeException("订单不存在,或者订单状态无效");
        }
        if(order.getStatus()!=1){
            order.setStatus(1);
        }else{
            order.setStatus(0);
        }

        return inventoryOrderMapper.updateById(order) == 1;
    }

    @Override
    public List<ErpInventoryOrderItem> orderItemByOrderSn(String orderSn) {

        ErpInventoryOrder order = selectByOrderSn(orderSn);
        Preconditions.checkNotNull(order, "订单不存在");
        QueryWrapper<ErpInventoryOrderItem> wrapper = new QueryWrapper<>();
        wrapper.eq("order_id", order.getId());
        final int status = order.getStatus();
        List<ErpInventoryOrderItem> items = inventoryOrderItemMapper.selectList(wrapper);
        items.forEach(x -> {
            ErpGoods goods = getGoods(x.getGoodsId());
            if (status == 1) {
                x.setRealNum(selectGoodsNumInTheShelf(x.getGoodsId(), x.getWhId()));
            }
            goods.setErpBrand(erpBrandMapper.selectById(goods.getBrandId()));
            goods.setErpCategory(erpCategoryMapper.selectById(goods.getCatId()));
            goods.setErpSupplier(erpSupplierMapper.selectById(goods.getSuppliersId()));
            ErpWarehouse erpWarehouse = erpWarehouseMapper.selectById(x.getWhId());
            x.setWarehouse(erpWarehouse);
            x.setGoods(goods);
            x.setRealPrice(goods.getShopPrice());
            x.setLeaveNum(leaveItemMapper.leaveNum(x.getId()));
        });
        return items;

    }

    @Override
    @Transactional
    public boolean updateOrder(String orderSn) {
        final ErpInventoryOrder order = selectByOrderSn(orderSn);
        if (order == null) {
            return false;
        }
        List<ErpInventoryOrderItem> items = orderItemByOrderSn(orderSn);
        if (order.getStatus() == 0) {
            //订单由草稿 --> 审核中
            order.setStatus(1);
            items.forEach(x -> {
                /**
                 * 现在只返回对应货位上的数量
                 */
                x.setRealNum(selectGoodsNumInTheShelf(x.getGoodsId(), x.getWhId()));
                inventoryOrderItemMapper.updateById(x);
            });
            return inventoryOrderMapper.updateById(order) == 1;
        }
        if (order.getStatus() == 1) {
            //订单由审核中 --> 审核成功
            order.setStatus(2);
            order.setIsRecom(1);
            items.forEach(x -> {
                //改变货架上仓库的值,并且改变goods的库存值
                logger.info(" item is null = {}", x == null);
                updateTheShelfNum(order, x);
                if (order.getMode()==1||order.getMode()==2){
                    QueryWrapper<Balance> wrapper = new QueryWrapper<>();
                    wrapper.eq("goods_id", x.getGoodsId());
                    wrapper.orderByAsc("create_time");
                    List<Balance> balances = balanceMapper.selectList(wrapper);
                    if (balances != null && balances.size() > 0) {
                        if (balances.size() == 1) {
                            Balance balance = balances.get(0);
                            balance.setGoodsNum(balance.getGoodsNum() - x.getInventoryNum());
                            balanceMapper.updateById(balance);
                        } else {
                            int num = x.getInventoryNum();
                            int tem = 0;
                            for (Balance balance : balances) {
                                if (balance.getGoodsNum() < 0) {
                                    continue;
                                }
                                num = num - balance.getGoodsNum();
                                if (num > 0) {
                                    balance.setGoodsNum(0);
                                    balanceMapper.updateById(balance);
                                } else {
                                    balance.setGoodsNum((-1)*num);
                                    balanceMapper.updateById(balance);
                                    break;
                                }
                            }
                        }
                    }
                }
            });
            return inventoryOrderMapper.updateById(order) == 1;
        }
        if (order.getStatus() == 4) {
            //订单由审核中 --> 审核成功
            order.setStatus(2);
            order.setIsRecom(1);
            long checkTime = GoodDateUtil.dateToStamp2(order.getCreateTime())/1000;
            if (checkTime <= ErpFinanceLogController.TIME){
                items.forEach(x -> {
                    //改变货架上仓库的值,并且改变goods的库存值
                    logger.info(" item is null = {}",  x == null);
                    updateTheShelfNum(order, x);

                });
            }
            return inventoryOrderMapper.updateById(order) == 1;
        }
        return false;
    }

    @Override
    public IPage<ErpInventoryOrder> page(String search, int current, int size) {
        Page<ErpInventoryOrder> page = new Page<>(current, size);
        QueryWrapper<ErpInventoryOrder> wrapper = new QueryWrapper<>();
        wrapper.apply(search).orderByDesc("id");
        return inventoryOrderMapper.selectPage(page, wrapper);
    }


    @Override
    @Transactional
    public ErpInventoryOrder createOrderByStatus(int mode, String orderSn, String context, final int status, AdminUser user, List<ErpInventoryOrderItem> orderItems, int type, String target) {
        ErpInventoryOrder order = selectByOrderSn(orderSn);
        boolean needUp = false;
        if (orderItems.isEmpty()) {
            throw new RuntimeException("订单项目不能为空");
        }
        if (status != 0 && status != 1) {
            throw new RuntimeException("订单状态异常");
        }
        if (order == null) {
            //新建订单
            order = new ErpInventoryOrder();
            needUp = true;
        }
        order.setContext(context);
        order.setMode(mode);
        order.setOperator(user.getUserName());
        order.setStatus(status);
        order.setCreateTime(LocalDateTime.now());
        order.setInventorySn(orderSn);
        order.setIsRecom(0);
        order.setType(type);
        order.setTarget(target);
        if (needUp) {
            inventoryOrderMapper.insert(order);
        } else {
            inventoryOrderMapper.updateById(order);
        }
        final int orderId = order.getId();
        reviewOrder(order, orderItems, (x) -> {
            if (status == 1) {
                x.setRealNum(selectGoodsNumInTheShelf(x.getGoodsId(), x.getWhId()));
            }
            x.setOrderId(orderId);
            inventoryOrderItemMapper.insert(x);
        });
//        for (ErpInventoryOrderItem erpInventoryOrderItem:orderItems){
//            if (erpInventoryOrderItem.getWhId()==6296||erpInventoryOrderItem.getWhId()==4) {
//                ErpWarehouseItem erpWarehouseItem = erpWarehouseItemMapper.selectItemByGoodsIdAndWhId(erpInventoryOrderItem.getGoodsId(), erpInventoryOrderItem.getWhId());
//                if (erpWarehouseItem != null) {
//                    erpWarehouseItem.setStock(erpWarehouseItem.getStock() + erpInventoryOrderItem.getInventoryNum());
//                    erpWarehouseItemMapper.updateById(erpWarehouseItem);
//                } else {
//                    erpWarehouseItem = new ErpWarehouseItem();
//                    erpWarehouseItem.setStock(erpInventoryOrderItem.getInventoryNum());
//                    erpWarehouseItem.setGoodsId(erpInventoryOrderItem.getGoodsId());
//                    erpWarehouseItem.setWhId(erpInventoryOrderItem.getWhId());
//                    erpWarehouseItemMapper.insert(erpWarehouseItem);
//                }
//            }else{
//                    int count = erpWarehouseMapper.foundGoodsCountInWarehouse(erpInventoryOrderItem.getGoodsId(), erpInventoryOrderItem.getWhId());
//                    if (count != 0) {
//                        throw new RuntimeException("选择的货位上已有其他商品！");
//                    }else{
//                        ErpWarehouseItem erpWarehouseItem = new ErpWarehouseItem();
//                        erpWarehouseItem.setStock(erpInventoryOrderItem.getInventoryNum());
//                        erpWarehouseItem.setGoodsId(erpInventoryOrderItem.getGoodsId());
//                        erpWarehouseItem.setWhId(erpInventoryOrderItem.getWhId());
//                        erpWarehouseItemMapper.insert(erpWarehouseItem);
//                    }
//
//            }
//        }
        return order;
    }


    @Override
    public boolean deleteOrderById(int id) {
        ErpInventoryOrder order = inventoryOrderMapper.selectById(id);
        if (order == null) {
            return false;
        }
        if (order.getStatus() != 0 && order.getStatus() != 1) {
            return false;
        }
        QueryWrapper<ErpInventoryOrderItem> wrapper = new QueryWrapper<>();
        wrapper.eq("order_id", id);
        inventoryOrderItemMapper.delete(wrapper);
        return 1 == inventoryOrderMapper.deleteById(id);
    }

    @Override
    @Transactional
    public boolean flushOrder(String orderSn, List<ErpInventoryOrderItem> orderItems) {
        ErpInventoryOrder order = selectByOrderSn(orderSn);
        if (order == null) {
            throw new RuntimeException("没有发现对应订单!");
        }
        if (order.getStatus() != 2 && order.getStatus() != 1) {
            throw new RuntimeException("订单状态只能是,待审核和审核通过");
        }
        if (order.getMode() != 0) {
            throw new RuntimeException("只能对盘库单进行提交遗漏!");
        }
        orderItems.forEach(x -> {
            ErpInventoryOrderItem orderItem = getOrderItemByOrderIdAndGoodsId(order.getId(), x.getGoodsId(), x.getWhId());
            if (orderItem == null) {
                throw new RuntimeException("没有这个盘点项");
//                orderItem = x;
//                orderItem.setOrderId(order.getId());
//                inventoryOrderItemMapper.insert(orderItem);
            } else {

                orderItem.setInventoryNum(orderItem.getInventoryNum() + x.getInventoryNum());
                leaveItemMapper.insert(new ErpLeaveItem(orderItem.getId(), x.getInventoryNum()));
                inventoryOrderItemMapper.updateById(orderItem);
            }
            if (order.getStatus() == 2) {
                updateTheShelfNum(order, orderItem);
            }
        });
        return inventoryOrderMapper.updateById(order) == 1;
    }

    private ErpInventoryOrderItem getOrderItemByOrderIdAndGoodsId(int orderId, int goodsId, int whId) {
        QueryWrapper<ErpInventoryOrderItem> wrapper = new QueryWrapper<>();
        wrapper.eq("order_id", orderId).eq("goods_id", goodsId).eq("wh_id", whId);
        return inventoryOrderItemMapper.selectOne(wrapper);
    }


    @Transactional
    public void updateTheShelfNum(ErpInventoryOrder order, ErpInventoryOrderItem x) {

        int mode = order.getMode();
        QueryWrapper<ErpWarehouseItem> wrapper = new QueryWrapper<>();
        wrapper.eq("goods_id", x.getGoodsId()).eq("wh_id", x.getWhId());
        ErpWarehouseItem item = warehouseItemMapper.selectOne(wrapper);
        ErpGoods goods = erpGoodMapper.selectById(x.getGoodsId());

        Preconditions.checkNotNull(goods, "没有发现对应商品ID{" + x.getGoodsId() + "}");

        switch (mode) {
            case 0: //盘货单
                if (item == null) {
                    item = new ErpWarehouseItem();
                    item.setStock(x.getInventoryNum());
                    item.setWhId(x.getWhId());
                    item.setGoodsId(x.getGoodsId());
                    warehouseItemMapper.insert(item);
                    goods.setGoodsNumber(warehouseItemMapper.getGoodsNumber(goods.getGoodsId()));
                } else {
                    item.setStock(x.getInventoryNum());
                    warehouseItemMapper.updateById(item);
                    //null pointer
                    goods.setGoodsNumber(
                            warehouseItemMapper.getGoodsNumberNotWhId(goods.getGoodsId(), item.getWhId()) + item.getStock());
                }
                if (x.getInventoryPrice()!=null){
                    goods.setShopPrice(x.getInventoryPrice());
                }else {
                    goods.setShopPrice(new BigDecimal(0));
                }

                break;
            case 1: //报损单
                if (item == null) {

                    throw new RuntimeException("没有发现货架上的商品{" + goods.getGoodsName() + "}!");
                } else {
                    int realStock = item.getStock();
                    if (goods.getGoodsNumber() < 0) {
                        throw new RuntimeException("领取超出商品{" + goods.getGoodsName() + "}数量的数量!");
                    }
                    item.setStock(realStock - x.getInventoryNum());
                    if (item.getStock() < 0) {
                        throw new RuntimeException("领取超出货架{" + item.getWhId() + "}上的商品{" + goods.getGoodsName() + "}数量，" +
                                "货架上只有数量{" + item.getStock() + "}！");
                    }
                    warehouseItemMapper.updateById(item);
                    goods.setGoodsNumber(warehouseItemMapper.getGoodsNumberNotWhId(goods.getGoodsId(), x.getWhId()) + item.getStock());
                }
                break;
            case 2: //领用单
                if (item == null) {
                    throw new RuntimeException("没有发现货架上的商品{" + goods.getGoodsName() + "}!");
                } else {
                    int realStock = item.getStock();
                    if (goods.getGoodsNumber() < 0) {
                        throw new RuntimeException("领取超出商品{" + goods.getGoodsName() + "}数量的数量!");
                    }
                    item.setStock(realStock - x.getInventoryNum());
                    if (item.getStock() < 0) {
                        throw new RuntimeException("领取超出货架{" + item.getWhId() + "}上的商品{" + goods.getGoodsName() + "}数量，" +
                                "货架上只有数量{" + item.getStock() + "}！");
                    }
                    warehouseItemMapper.updateById(item);
                    goods.setGoodsNumber(warehouseItemMapper.getGoodsNumberNotWhId(goods.getGoodsId(), x.getWhId()) + item.getStock());
                }
                break;
            case 3: //退货单
                if (order.getType() == 0) {
                    //直接入库
                    if (item == null) {
                        item = new ErpWarehouseItem();
                        item.setStock(x.getInventoryNum());
                        item.setWhId(x.getWhId());
                        item.setGoodsId(x.getGoodsId());
                        warehouseItemMapper.insert(item);
                        goods.setGoodsNumber(warehouseItemMapper.getGoodsNumber(goods.getGoodsId()));
                    } else {
                        int realStock = item.getStock();
                        item.setStock(realStock + x.getInventoryNum());
                        warehouseItemMapper.updateById(item);
                        goods.setGoodsNumber(warehouseItemMapper.getGoodsNumberNotWhId(goods.getGoodsId(), item.getWhId()) + item.getStock());
                    }
                } else if (order.getType() == 1) {
                    //直接出库
                    if (item == null) {
                        throw new RuntimeException("商品:" + goods.getGoodsName() + " 对应货位上没有商品");
                    }
                    if (item.getStock() < x.getInventoryNum()) {
                        throw new RuntimeException("商品:" + goods.getGoodsName() + " 对应货位id:" + item.getWhId() + "上商品不够!");
                    }
                    int realStock = item.getStock();
                    item.setStock(realStock - x.getInventoryNum());
                    warehouseItemMapper.updateById(item);
                    goods.setGoodsNumber(warehouseItemMapper.getGoodsNumberNotWhId(goods.getGoodsId(), item.getWhId()) + item.getStock());
                }
                break;
            default:
                throw new RuntimeException("没有发现对应订单模式");
        }
        erpGoodMapper.updateById(goods);
    }


    /**
     * 订单项目重置
     *
     * @param order
     * @param items
     */
    private void reviewOrder(final ErpInventoryOrder order, List<ErpInventoryOrderItem> items, Consumer<ErpInventoryOrderItem> consumer) {
        //删除该订单下的所有原始数据
        QueryWrapper<ErpInventoryOrderItem> wrapper = new QueryWrapper<>();
        wrapper.eq("order_id", order.getId());
        inventoryOrderItemMapper.delete(wrapper);
        items.forEach(consumer);
    }

    private ErpInventoryOrder selectByOrderSn(String orderSn) {
        QueryWrapper<ErpInventoryOrder> wrapper = new QueryWrapper<>();
        wrapper.eq("inventory_sn", orderSn);
        return inventoryOrderMapper.selectOne(wrapper);
    }


    /**
     * 查询当前仓库上商品的数量
     *
     * @param goodsId 商品ID
     * @param whId    仓库ID
     * @return
     */
    private int selectGoodsNumInTheShelf(int goodsId, int whId) {
        QueryWrapper<ErpWarehouseItem> wrapper = new QueryWrapper<>();
        wrapper.eq("goods_id", goodsId).eq("wh_id", whId);
        ErpWarehouseItem item = warehouseItemMapper.selectOne(wrapper);
        if (item == null) {
            return 0;
        }
        return item.getStock();
    }

    /**
     * 获取Goods的库存数量
     *
     * @param goodsId
     * @return
     */
    private ErpGoods getGoods(int goodsId) {
        QueryWrapper<ErpGoods> wrapper = new QueryWrapper<>();
        wrapper.eq("goods_id", goodsId);
        ErpGoods goods = erpGoodMapper.selectOne(wrapper);
        return goods;
    }

    @Override
    @Transactional
    public ErpInventoryOrder passOrder(String orderInfo, int userId) {
        AdminUser user = adminUserMapper.selectById(userId);
        Preconditions.checkNotNull(user, "用户不存在!");
        final ErpInventoryOrder order = inventoryOrderMapper.selectByInSn(orderInfo);
        if (order == null) {
            throw new RuntimeException("无法查询到对应订单");
        }
        if (order.getStatus() == 1) {
            AdminUser adminUser = adminUserMapper.selectOneByName(order.getTarget());
            Supplier supplier =  supplierMapper.selectSupplierByName(order.getTarget());
            List<ErpInventoryOrderItem> erpInventoryOrderItem = inventoryOrderItemMapper.selectReturnMoney(order.getId());
            double b=0;
            if (erpInventoryOrderItem.size()>1){
                for(int i=0;i<erpInventoryOrderItem.size();i ++){
                    b +=erpInventoryOrderItem.get(i).getInventoryPrice().doubleValue()*erpInventoryOrderItem.get(i).getInventoryNum();
                }
            }else {
                b=erpInventoryOrderItem.get(0).getInventoryPrice().doubleValue()*erpInventoryOrderItem.get(0).getInventoryNum();
            }
            ErpFinanceLog log = new ErpFinanceLog();
            //财务审核到 -- 订单审核
            if (adminUser!=null){
                log.setOrderNumber("FK" + Instant.now().toEpochMilli());
                log.setOrderSn(order.getInventorySn());
                log.setChecktime(LocalDateTime.now());
                log.setReturnMoney(BigDecimal.valueOf(b));
                log.setStatus(ErpOrderStatus.submit.getStatus());
                log.setTotal(BigDecimal.valueOf(b));
                log.setStoreName(String.valueOf(adminUser.getUserId()));
                log.setMode(ErpFinanceLog.MODE_RECEIPT);
                log.setRemark(order.getContext());
                //初始化反点金额
                BigDecimal rebateRate = adminUser.getRebateRate();
                if (rebateRate == null || rebateRate.doubleValue() == 0.0) {
                    rebateRate = BigDecimal.ZERO;
                }

                BigDecimal rebate = log.getSubTotal().multiply(rebateRate);
                log.setRebate(rebate);
                log.setUserBalance(adminUser.getBalance());
                log.setCreater(user.getUserName());
            }else if (supplier!=null){
                log.setOrderNumber("SK" + Instant.now().toEpochMilli());
                b = 0-b;
                log.setOrderSn(order.getInventorySn());
                log.setChecktime(LocalDateTime.now());
                log.setReturnMoney(BigDecimal.valueOf(b));
                log.setStatus(ErpOrderStatus.submit.getStatus());
                log.setStoreName(String.valueOf(supplier.getSuppliersId()));
                log.setMode(ErpFinanceLog.MODE_PAYMENT);
                log.setRemark(order.getContext());
                log.setTotal(BigDecimal.valueOf(b));
                //初始化反点金额
                List<Double> s = contractMapper.getSupIdCashBack(supplier.getSuppliersId());
                double sum=0;
                if (s.size()>=1){
                    for (Double d:s){
                        sum +=d;
                    }
                }
                log.setRebate(BigDecimal.valueOf(sum));
                log.setUserBalance(supplier.getBalance());
                log.setCreater(user.getUserName());
            }
            erpFinanceLogMapper.insert(log);
            List<ErpInventoryOrderItem> items = orderItemByOrderSn(orderInfo);

            items.forEach(x -> {
                //改变货架上仓库的值,并且改变goods的库存值
                logger.info(" item is null = {}",  x == null);
                updateTheShelfNum(order, x);

            });
            order.setCreateTime(LocalDateTime.now());
            order.setStatus(ErpOrderStatus.finance.getStatus());
        }
        if (inventoryOrderMapper.updateById(order) == 1) {
            return order;
        }

        throw new RuntimeException("订单更新失败!");
    }
}
